package cn.huiyunche.base.service.interfaces.impl;

import cn.huiyunche.base.service.interfaces.JPushService;
import cn.jpush.api.JPushClient;
import cn.jpush.api.common.resp.APIConnectionException;
import cn.jpush.api.common.resp.APIRequestException;
import cn.jpush.api.push.PushResult;
import cn.jpush.api.push.model.Options;
import cn.jpush.api.push.model.Platform;
import cn.jpush.api.push.model.PushPayload;
import cn.jpush.api.push.model.audience.Audience;
import cn.jpush.api.push.model.notification.AndroidNotification;
import cn.jpush.api.push.model.notification.IosNotification;
import cn.jpush.api.push.model.notification.Notification;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 极光推送通知
 * Created by LYN on 8/8/16.
 */
@Service
@EnableAsync
public class JPushServiceImpl implements JPushService {

    private static final Logger LOG = LoggerFactory.getLogger(JPushServiceImpl.class);

    @Value("${jpush.appKey.driver}")
    private String appKey_kyle;
    @Value("${jpush.masterSecret.driver}")
    private String masterSecret_kyle;

    @Value("${jpush.appKey.stan}")
    private String appKey_stan;
    @Value("${jpush.masterSecret.stan}")
    private String masterSecret_stan;

    @Value("${jpush.appKey.stancity}")
    private String appKey_stancity;
    @Value("${jpush.masterSecret.stancity}")
    private String masterSecret_stancity;

    @Value("${jpush.appKey.driver}")
    private String appKey_driver;
    @Value("${jpush.masterSecret.driver}")
    private String masterSecret_driver;

    /**
     * @param registrationIds 为空则通知全部用户, 不建议为空。
     * @param msgContent
     * @return
     */
    public boolean sendMsgKyle(List<String> registrationIds, String msgContent) {
        LOG.info("app driver push notify: regid:{}, msg:{}", JSON.toJSONString(registrationIds), msgContent);
        return sendMsg(masterSecret_kyle, appKey_kyle, registrationIds, msgContent);
    }

    public boolean sendMsgStan(List<String> registrationIds, String msgContent) {
        LOG.info("app stan push notify: regid:{}, msg:{}", JSON.toJSONString(registrationIds), msgContent);
        return sendMsg(masterSecret_stan, appKey_stan, registrationIds, msgContent);
    }

    public boolean sendMsgStanByAliases(List<String> aliases, String msgContent, String tag) {
        LOG.info("app stan push notify: regid:{}, msg:{}, params: {}", JSON.toJSONString(aliases), msgContent, tag);
        return sendMsgByAliases(masterSecret_stan, appKey_stan, aliases, msgContent, tag);
    }

    public boolean sendMsgStanCityByAliases(List<String> aliases, String msgContent, String tag) {
        LOG.info("app stan push notify: regid:{}, msg:{}, params: {}", JSON.toJSONString(aliases), msgContent, tag);
        return sendMsgByAliases(masterSecret_stancity, appKey_stancity, aliases, msgContent, tag);
    }

    @Override
    public boolean sendMsgKyleByAliases(List<String> aliases, String msgContent) {
        LOG.info("app driver push notify: regid:{}, msg:{}", JSON.toJSONString(aliases), msgContent);
        return sendMsgByAliases(masterSecret_kyle, appKey_kyle, aliases, msgContent, "0");
    }

    @Override
    public boolean sendMsgDriverByAliases(List<String> registrationIds, String msgContent, String tag) {
        LOG.info("app stan push notify: regid:{}, msg:{}, params: {}", JSON.toJSONString(registrationIds), msgContent, tag);
        return sendMsgByAliases(masterSecret_driver, appKey_driver, registrationIds, msgContent, tag);
    }


    /**
     * 根据别名推送消息
     *
     * @param registrationIds
     * @param msgContent
     * @return
     */
    private boolean sendMsgByAliases(String masterSecret, String appkey, List<String> aliases, String msgContent, String tag) {
        boolean isSend = true;
        JPushClient jPushClient = new JPushClient(masterSecret, appkey);
        PushPayload payload = null;
        if (null != aliases && aliases.size() > 0) {
            payload = buildPushObjectByAlias(aliases, msgContent, tag);
        } else {
            payload = buildPushObject_all_all_alert(msgContent);
        }
        try {
            PushResult result = jPushClient.sendPush(payload);
            LOG.info("jpush :Got result {} ", result);
        } catch (APIConnectionException e) {
            isSend = false;
            // Connection error, should retry later
            LOG.error("jpush error: Connection error, should retry later: {}", e);
        } catch (APIRequestException e) {
            isSend = false;
            // Should review the error, and fix the request
            LOG.error("jpush error: Should review the error, and fix the request: {}", e);
            LOG.info("HTTP Status: {}", e.getStatus());
            LOG.info("Error Code: {}", e.getErrorCode());
            LOG.info("Error Message: {}", e.getErrorMessage());
        }
        return isSend;
    }

    /**
     * 推送消息
     *
     * @param registrationIds
     * @param msgContent
     * @return
     */
    private boolean sendMsg(String masterSecret, String appkey, List<String> registrationIds, String msgContent) {
        boolean isSend = true;
        JPushClient jPushClient = new JPushClient(masterSecret, appkey);
        PushPayload payload = null;
        if (null != registrationIds && registrationIds.size() > 0) {
            payload = buildPushObject_all_regids_alert(registrationIds, msgContent);
        } else {
            payload = buildPushObject_all_all_alert(msgContent);
        }
        try {
            PushResult result = jPushClient.sendPush(payload);
            LOG.info("jpush :Got result {} ", result);
        } catch (APIConnectionException e) {
            isSend = false;
            // Connection error, should retry later
            LOG.error("jpush error: Connection error, should retry later: {}", e);
        } catch (APIRequestException e) {
            isSend = false;
            // Should review the error, and fix the request
            LOG.error("jpush error: Should review the error, and fix the request: {}", e);
            LOG.info("HTTP Status: {}", e.getStatus());
            LOG.info("Error Code: {}", e.getErrorCode());
            LOG.info("Error Message: {}", e.getErrorMessage());
        }
        return isSend;
    }

    /**
     * 广播所有人
     *
     * @param content
     * @return
     */
    private PushPayload buildPushObject_all_all_alert(String content) {
        return PushPayload.alertAll(content);
    }

    /**
     * 指定注册ID 用户
     *
     * @param registrationIds
     * @param content
     * @return
     */
    private PushPayload buildPushObject_all_regids_alert(List<String> registrationIds, String content) {
        return PushPayload.newBuilder()
                .setPlatform(Platform.all())
                .setAudience(Audience.registrationId(registrationIds))
                .setNotification(Notification.newBuilder()
                        .addPlatformNotification(IosNotification.newBuilder()
                                .setAlert(content)
                                .setSound("default")
                                .build())
                        .addPlatformNotification(AndroidNotification.newBuilder()
                                .setAlert(content).build())
                        .build())
                //.setNotification(Notification.alert(content))
                .setOptions(Options.newBuilder().setApnsProduction(true).build())
                .build();
    }

    /**
     * 指定别名 用户
     *
     * @param registrationIds
     * @param content
     * @return
     */
    private PushPayload buildPushObjectByAlias(List<String> aliases, String content, String tag) {
        return PushPayload.newBuilder()
                .setPlatform(Platform.all())
                .setAudience(Audience.alias(aliases))
                .setNotification(Notification.newBuilder()
                        .addPlatformNotification(IosNotification.newBuilder().setAlert(content).setBadge(1).setSound("default").setContentAvailable(true).addExtra("tag", tag).build())
                        .addPlatformNotification(AndroidNotification.newBuilder().setAlert(content).addExtra("tag", tag).build()).build())
                .setOptions(Options.newBuilder().setApnsProduction(true).build())
                .build();
    }


}
